package com.lonely.inventory.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.Cascader;
import com.lonely.common.core.domain.Select;
import com.lonely.common.core.page.Condition;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.enums.DataScope;
import com.lonely.common.exception.BusinessException;
import com.lonely.common.threadlocals.DataPermissionThreadLocal;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.inventory.domain.dto.storagearchive.*;
import com.lonely.inventory.domain.entity.SysInventoryStorageArchive;
import com.lonely.inventory.domain.vo.storagearchive.StorageArchivePageQueryVo;
import com.lonely.inventory.enums.StorageArchiveEnum;
import com.lonely.inventory.mapper.SysInventoryStorageArchiveMapper;
import com.lonely.inventory.service.IStorageArchiveService;
import com.lonely.inventory.utils.GeneratorPrintStorageCodePdfUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/9/17 17:08
 * @description: 库位档案服务实现类
 */
@Service
public class StorageArchiveServiceImpl extends ServiceImpl<SysInventoryStorageArchiveMapper, SysInventoryStorageArchive> implements IStorageArchiveService {


    /**
     * 分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<StorageArchivePageQueryVo> page(StorageArchivePageQueryDto queryDto) {
        DataPermissionThreadLocal.setDataPermission(DataScope.FACTORY, "factory_id");
        Page<StorageArchivePageQueryVo> page = Condition.page(queryDto);
        page = super.getBaseMapper().page(page, queryDto);

        return page;
    }

    /**
     * 创建库位
     *
     * @param submitDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveAndPrint(List<StorageArchiveSubmitDto> submitDto) {
        if (CollUtil.isEmpty(submitDto)) {
            throw new BusinessException("参数错误");
        }

        List<List<PrintStorageCodeBodyDTO>> printStorageCodeGroups = new ArrayList<>();

        for (StorageArchiveSubmitDto archiveSubmitDto : submitDto) {
            List<SysInventoryStorageArchive> currentGroupStorageArchives = new ArrayList<>();

            // 找到当前库位最新的库位号
            SysInventoryStorageArchive lastStorageArchive = super.getOne(new LambdaQueryWrapper<SysInventoryStorageArchive>()
                    .eq(SysInventoryStorageArchive::getStorageType, archiveSubmitDto.getStorageType())
                    .eq(SysInventoryStorageArchive::getStoragePrefix, archiveSubmitDto.getStoragePrefix())
                    .orderByDesc(SysInventoryStorageArchive::getStorageNum)
                    .last("limit 1")
            );
            int lastStorageNum = lastStorageArchive == null ? 0 : lastStorageArchive.getStorageNum();

            for (int i = 1; i <= archiveSubmitDto.getAddStorageNum(); i++) {
                SysInventoryStorageArchive storageArchive = new SysInventoryStorageArchive();
                // 验证库位类型是否正确
                StorageArchiveEnum.StorageTypeEnum.getInstanceByStorageTypeCode(archiveSubmitDto.getStorageType());
                storageArchive.setStorageType(archiveSubmitDto.getStorageType());
                storageArchive.setStoragePrefix(archiveSubmitDto.getStoragePrefix());

                lastStorageNum += 1;
                int currentStorageNum = lastStorageNum;
                storageArchive.setStorageNum(currentStorageNum);
                storageArchive.setStorageName(String.format("%s-%s-%s", archiveSubmitDto.getStorageType(), archiveSubmitDto.getStoragePrefix(), currentStorageNum));
                storageArchive.setFactoryId(archiveSubmitDto.getFactoryId());
                storageArchive.setCreateBy(SecurityUtils.getUserId());
                storageArchive.setUpdateBy(SecurityUtils.getUserId());
                storageArchive.setRemark(archiveSubmitDto.getRemark());
                currentGroupStorageArchives.add(storageArchive);
            }

            // 入库
            super.saveBatch(currentGroupStorageArchives);

            // 构建当前组的库位码对象
            printStorageCodeGroups.add(currentGroupStorageArchives.stream().map(x -> {
                StorageArchiveEnum.StorageTypeEnum storageTypeEnum = StorageArchiveEnum.StorageTypeEnum.getInstanceByStorageTypeCode(x.getStorageType());
                PrintStorageCodeBodyDTO printStorageCodeBodyDTO = new PrintStorageCodeBodyDTO();
                printStorageCodeBodyDTO.setStorageType(storageTypeEnum.getStorageTypeCode());
                printStorageCodeBodyDTO.setStorageTypeName(storageTypeEnum.getStorageTypeName());
                printStorageCodeBodyDTO.setStorageCode(x.getStorageName());
                printStorageCodeBodyDTO.setFactoryId(x.getFactoryId());
                return printStorageCodeBodyDTO;
            }).collect(Collectors.toList()));
        }

        // 打印库位码pdf
        return GeneratorPrintStorageCodePdfUtil.generatorStorageCodePdfAndUploadToMinio(printStorageCodeGroups);
    }

    /**
     * 删除库位
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStorageArchive(Long id) {
        super.removeById(id);
    }

    /**
     * 打印库位码
     *
     * @param printStorageCodeDTO
     * @return
     */
    @Override
    public String printStorageCode(PrintStorageCodeDTO printStorageCodeDTO) {
        List<SysInventoryStorageArchive> storageArchives = super.list(new LambdaQueryWrapper<SysInventoryStorageArchive>()
                .in(SysInventoryStorageArchive::getId, printStorageCodeDTO.getStorageArchiveIds())
                .eq(SysInventoryStorageArchive::getStatus, CommonStatus.ENABLE.code)
                .orderByAsc(SysInventoryStorageArchive::getStorageType, SysInventoryStorageArchive::getStoragePrefix)
        );
        if (CollUtil.isEmpty(storageArchives)) {
            throw new BusinessException("没有查询到库位信息..");
        }

        // 将库位信息分组
        Map<String, List<PrintStorageCodeBodyDTO>> printStorageCodeGroupMap = new LinkedHashMap<>();
        for (SysInventoryStorageArchive storageArchive : storageArchives) {
            PrintStorageCodeBodyDTO printStorageCodeBodyDTO = new PrintStorageCodeBodyDTO();
            StorageArchiveEnum.StorageTypeEnum storageTypeEnum = StorageArchiveEnum.StorageTypeEnum.getInstanceByStorageTypeCode(storageArchive.getStorageType());
            printStorageCodeBodyDTO.setStorageType(storageTypeEnum.getStorageTypeCode());
            printStorageCodeBodyDTO.setStorageTypeName(storageTypeEnum.getStorageTypeName());
            printStorageCodeBodyDTO.setStorageCode(storageArchive.getStorageName());
            printStorageCodeBodyDTO.setFactoryId(storageArchive.getFactoryId());

            String key = String.format("%s-%s", storageArchive.getStorageType(), storageArchive.getStoragePrefix());
            printStorageCodeGroupMap.computeIfAbsent(key, k -> new ArrayList<>()).add(printStorageCodeBodyDTO);
//            if(printStorageCodeGroups.containsKey(key)){
//                printStorageCodeGroups.get(key).add(printStorageCodeBodyDTO);
//            }else {
//                List<PrintStorageCodeBodyDTO> printStorageCodeBodyDTOS = new ArrayList<>();
//                printStorageCodeBodyDTOS.add(printStorageCodeBodyDTO);
//                printStorageCodeGroups.put(key, printStorageCodeBodyDTOS);
//            }

        }

        // 打印库位码pdf
        List<List<PrintStorageCodeBodyDTO>> printStorageCodeGroups = new ArrayList<>(printStorageCodeGroupMap.values());
        return GeneratorPrintStorageCodePdfUtil.generatorStorageCodePdfAndUploadToMinio(printStorageCodeGroups);
    }

    /**
     * 批量删除库位档案
     *
     * @param batchDeleteStorageArchiveDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteStorageArchive(BatchDeleteStorageArchiveDTO batchDeleteStorageArchiveDTO) {
        super.removeByIds(batchDeleteStorageArchiveDTO.getStorageArchiveIds());
    }

    /**
     * 获取库位码级联数据
     *
     * @return
     */
    @Override
    public List<Cascader> getStorageCodeCascader() {
        List<SysInventoryStorageArchive> inventoryStorageArchives = super.list(new LambdaQueryWrapper<SysInventoryStorageArchive>()
                .eq(SysInventoryStorageArchive::getStatus, CommonStatus.ENABLE.code)
        );

        List<Cascader> cascaders = new ArrayList<>();
        Map<String, List<SysInventoryStorageArchive>> inventoryStoragePrefixMap = inventoryStorageArchives.stream().collect(Collectors.groupingBy(SysInventoryStorageArchive::getStoragePrefix));
        for (StorageArchiveEnum.StoragePrefixEnum storagePrefixEnum : StorageArchiveEnum.StoragePrefixEnum.values()) {
            Cascader cascader = new Cascader();
            cascader.setLabel(storagePrefixEnum.name());
            cascader.setValue(storagePrefixEnum.name());
            if (inventoryStoragePrefixMap.containsKey(storagePrefixEnum.name())) {
                cascader.setChildren(inventoryStoragePrefixMap.get(storagePrefixEnum.name()).stream().map(x -> {
                    Cascader currentCascader = new Cascader();
                    currentCascader.setLabel(x.getStorageName());
                    currentCascader.setValue(x.getId());
                    return currentCascader;
                }).collect(Collectors.toList()));
            } else {
                cascader.setChildren(new ArrayList<>());
            }
            cascaders.add(cascader);
        }
        return cascaders;
    }

    /**
     * 根据库位码获取对应的库位档案信息
     *
     * @param storageCode
     * @return
     */
    @Override
    public SysInventoryStorageArchive getByStorageCode(String storageCode) {
        return super.getOne(new LambdaQueryWrapper<SysInventoryStorageArchive>()
                .eq(SysInventoryStorageArchive::getStorageName, storageCode)
                .eq(SysInventoryStorageArchive::getStatus, CommonStatus.ENABLE.code)
        );
    }

    /**
     * 获取备货库存类型的库位列表
     *
     * @return
     */
    @Override
    public List<Select> getStorageArchiveSelectByBhStorageType() {
        return super.list(new LambdaQueryWrapper<SysInventoryStorageArchive>()
                .eq(SysInventoryStorageArchive::getStorageType, StorageArchiveEnum.StorageTypeEnum.STOCK_UP_STORAGE.getStorageTypeCode())
                .eq(SysInventoryStorageArchive::getStatus, CommonStatus.ENABLE.code)
        ).stream().map(x -> {
            Select select = new Select();
            select.setLabel(x.getStorageName());
            select.setValue(Convert.toStr(x.getId()));
            return select;
        }).collect(Collectors.toList());
    }

}
